#include "aht10.h"
#include "driver/i2c.h"
#include "esp_log.h"


#define AHT10_SENSOR_ADDR 0x38
#define AHT10_CMD_CALIBRATE 0xE1
#define AHT10_CMD_TRIGGER 0xAC
#define AHT10_CMD_SOFT_RESET 0xBA

#define AHT10_MEASURE_DELAY_MS 100

static const char *TAG = "AHT11";

typedef struct
{
    uint8_t busy : 1;
    uint8_t mode : 2;
    uint8_t : 1;
    uint8_t cal : 1;
    uint8_t : 3;
}AHT10_sts;
AHT10_sts aht10_sts;

static esp_err_t aht10_write_command(i2c_port_t i2c_num, uint8_t cmd)
{
    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, AHT10_SENSOR_ADDR << 1 | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd_handle, cmd, true);
    i2c_master_stop(cmd_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd_handle, 1000);
    i2c_cmd_link_delete(cmd_handle);
    return ret;
}

static esp_err_t aht10_read_data(i2c_port_t i2c_num, uint8_t *data, size_t size)
{
    i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
    i2c_master_start(cmd_handle);
    i2c_master_write_byte(cmd_handle, AHT10_SENSOR_ADDR << 1 | I2C_MASTER_READ, true);
    if (size > 1) {
        i2c_master_read(cmd_handle, data, size - 1, I2C_MASTER_ACK);
    }
    i2c_master_read_byte(cmd_handle, data + size - 1, I2C_MASTER_NACK);
    i2c_master_stop(cmd_handle);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd_handle, 1000);
    i2c_cmd_link_delete(cmd_handle);
    return ret;
}

static esp_err_t aht10_calibrate(i2c_port_t i2c_num)
{
    return aht10_write_command(i2c_num, AHT10_CMD_CALIBRATE);
}

static esp_err_t aht10_trigger_measurement(i2c_port_t i2c_num)
{
    return aht10_write_command(i2c_num, AHT10_CMD_TRIGGER);
}

static esp_err_t aht10_soft_reset(i2c_port_t i2c_num)
{
    return aht10_write_command(i2c_num, AHT10_CMD_SOFT_RESET);
}

int aht10_init()
{
    i2c_config_t i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = AHT10_SDA_GPIO,
        .scl_io_num = AHT10_SCL_GPIO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 100000
    };
    i2c_param_config(AHT10_I2C_PORT, &i2c_config);
    i2c_driver_install(AHT10_I2C_PORT, I2C_MODE_MASTER, 0, 0, 0);

    aht10_soft_reset(AHT10_I2C_PORT);
    aht10_calibrate(AHT10_I2C_PORT);

    return 0;
}

int aht10_read(float *temperature, float *humidity)
{
    uint8_t data[6];

    if(!aht10_sts.busy)
    {
        aht10_trigger_measurement(AHT10_I2C_PORT);
        vTaskDelay(AHT10_MEASURE_DELAY_MS / portTICK_PERIOD_MS);
    }

    aht10_read_data(AHT10_I2C_PORT, data, sizeof(data));
    aht10_sts = *((AHT10_sts*)&data[0]);

    if(aht10_sts.busy || aht10_sts.mode == 0)//忙状态或模式为NOR，输出状态信息，并返回错误
    {
        ESP_LOGE(TAG, "busy %d, mode: %d, cal: %d", aht10_sts.busy, aht10_sts.mode, aht10_sts.cal);
        return 1;
    }
    else
    {
        uint32_t raw_humidity = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | ((uint32_t)data[3] >> 4);
        *humidity = (float)raw_humidity / 1048576.0f * 100.0f;

        uint32_t raw_temperature = ((uint32_t)data[3] & 0x0F) << 16 | ((uint32_t)data[4] << 8) | data[5];
        *temperature = (float)raw_temperature / 1048576.0f * 200.0f - 50.0f;
    }

    return 0;
}